home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / locking.c.z / locking.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  7.7 KB  |  264 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Locking functions
  5.    Copyright (C) Andrew Tridgell 1992-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.    Revision History:
  22.  
  23.    12 aug 96: Erik.Devriendt@te6.siemens.be
  24.    added support for shared memory implementation of share mode locking
  25.  
  26.    May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
  27.    locking to deal with multiple share modes per open file.
  28.  
  29.    September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
  30.    support.
  31.  
  32. */
  33.  
  34. #include "includes.h"
  35. extern int DEBUGLEVEL;
  36. extern connection_struct Connections[];
  37. extern files_struct Files[];
  38.  
  39. static struct share_ops *share_ops;
  40.  
  41. /****************************************************************************
  42.  Utility function to map a lock type correctly depending on the real open
  43.  mode of a file.
  44. ****************************************************************************/
  45.  
  46. static int map_lock_type( files_struct *fsp, int lock_type)
  47. {
  48.   if((lock_type == F_WRLCK) && (fsp->fd_ptr->real_open_flags == O_RDONLY)) {
  49.     /*
  50.      * Many UNIX's cannot get a write lock on a file opened read-only.
  51.      * Win32 locking semantics allow this.
  52.      * Do the best we can and attempt a read-only lock.
  53.      */
  54.     DEBUG(10,("map_lock_type: Downgrading write lock to read due to read-only file.\n"));
  55.     return F_RDLCK;
  56.   } else if( (lock_type == F_RDLCK) && (fsp->fd_ptr->real_open_flags == O_WRONLY)) {
  57.     /*
  58.      * Ditto for read locks on write only files.
  59.      */
  60.     DEBUG(10,("map_lock_type: Changing read lock to write due to write-only file.\n"));
  61.     return F_WRLCK;
  62.   }
  63.  
  64.   /*
  65.    * This return should be the most normal, as we attempt
  66.    * to always open files read/write.
  67.    */
  68.  
  69.   return lock_type;
  70. }
  71.  
  72. /****************************************************************************
  73.  Utility function called to see if a file region is locked.
  74. ****************************************************************************/
  75.  
  76. BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset,int lock_type)
  77. {
  78.   int snum = SNUM(cnum);
  79.   files_struct *fsp = &Files[fnum];
  80.  
  81.   if (count == 0)
  82.     return(False);
  83.  
  84.   if (!lp_locking(snum) || !lp_strict_locking(snum))
  85.     return(False);
  86.  
  87.   /*
  88.    * Note that most UNIX's can *test* for a write lock on
  89.    * a read-only fd, just not *set* a write lock on a read-only
  90.    * fd. So we don't need to use map_lock_type here.
  91.    */
  92.  
  93.   return(fcntl_lock(fsp->fd_ptr->fd,F_GETLK,offset,count,lock_type));
  94. }
  95.  
  96.  
  97. /****************************************************************************
  98.  Utility function called by locking requests.
  99. ****************************************************************************/
  100.  
  101. BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int lock_type,
  102.              int *eclass,uint32 *ecode)
  103. {
  104.   BOOL ok = False;
  105.   files_struct *fsp = &Files[fnum];
  106.  
  107.   if (!lp_locking(SNUM(cnum)))
  108.     return(True);
  109.  
  110.   if (count == 0) {
  111.     *eclass = ERRDOS;
  112.     *ecode = ERRnoaccess;
  113.     return False;
  114.   }
  115.  
  116.   if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum))
  117.     ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,
  118.                     map_lock_type(fsp,lock_type));
  119.  
  120.   if (!ok) {
  121.     *eclass = ERRDOS;
  122.     *ecode = ERRlock;
  123.     return False;
  124.   }
  125.   return True; /* Got lock */
  126. }
  127.  
  128.  
  129. /****************************************************************************
  130.  Utility function called by unlocking requests.
  131. ****************************************************************************/
  132.  
  133. BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode)
  134. {
  135.   BOOL ok = False;
  136.   files_struct *fsp = &Files[fnum];
  137.  
  138.   if (!lp_locking(SNUM(cnum)))
  139.     return(True);
  140.  
  141.   if (OPEN_FNUM(fnum) && fsp->can_lock && (fsp->cnum == cnum))
  142.     ok = fcntl_lock(fsp->fd_ptr->fd,F_SETLK,offset,count,F_UNLCK);
  143.  
  144.   if (!ok) {
  145.     *eclass = ERRDOS;
  146.     *ecode = ERRlock;
  147.     return False;
  148.   }
  149.   return True; /* Did unlock */
  150. }
  151.  
  152.  
  153.  
  154. /****************************************************************************
  155.  Initialise the locking functions.
  156. ****************************************************************************/
  157.  
  158. BOOL locking_init(int read_only)
  159. {
  160.     if (share_ops) return True;
  161.  
  162. #ifdef FAST_SHARE_MODES
  163.     share_ops = locking_shm_init(read_only);
  164.     if (!share_ops) {
  165.         DEBUG(0,("ERROR: Failed to initialise fast share modes - trying slow code\n"));
  166.     }
  167.     if (share_ops) return True;
  168. #endif    
  169.  
  170.     share_ops = locking_slow_init(read_only);
  171.     if (!share_ops) {
  172.         DEBUG(0,("ERROR: Failed to initialise share modes!\n"));
  173.         return False;
  174.     }
  175.     
  176.     return True;
  177. }
  178.  
  179. /*******************************************************************
  180.  Deinitialize the share_mode management.
  181. ********************************************************************/
  182.  
  183. BOOL locking_end(void)
  184. {
  185.     if (share_ops)
  186.         return share_ops->stop_mgmt();
  187.     return True;
  188. }
  189.  
  190.  
  191. /*******************************************************************
  192.  Lock a hash bucket entry.
  193. ********************************************************************/
  194.  
  195. BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
  196. {
  197.     return share_ops->lock_entry(cnum, dev, inode, ptok);
  198. }
  199.  
  200. /*******************************************************************
  201.  Unlock a hash bucket entry.
  202. ********************************************************************/
  203.  
  204. BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
  205. {
  206.     return share_ops->unlock_entry(cnum, dev, inode, token);
  207. }
  208.  
  209. /*******************************************************************
  210.  Get all share mode entries for a dev/inode pair.
  211. ********************************************************************/
  212.  
  213. int get_share_modes(int cnum, int token, uint32 dev, uint32 inode, 
  214.             share_mode_entry **shares)
  215. {
  216.     return share_ops->get_entries(cnum, token, dev, inode, shares);
  217. }
  218.  
  219. /*******************************************************************
  220.  Del the share mode of a file.
  221. ********************************************************************/
  222.  
  223. void del_share_mode(int token, int fnum)
  224. {
  225.     share_ops->del_entry(token, fnum);
  226. }
  227.  
  228. /*******************************************************************
  229.  Set the share mode of a file. Return False on fail, True on success.
  230. ********************************************************************/
  231.  
  232. BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
  233. {
  234.     return share_ops->set_entry(token, fnum, port, op_type);
  235. }
  236.  
  237. /*******************************************************************
  238.  Remove an oplock port and mode entry from a share mode.
  239. ********************************************************************/
  240.  
  241. BOOL remove_share_oplock(int fnum, int token)
  242. {
  243.     return share_ops->remove_oplock(fnum, token);
  244. }
  245.  
  246. /*******************************************************************
  247.  Call the specified function on each entry under management by the
  248.  share mode system.
  249. ********************************************************************/
  250.  
  251. int share_mode_forall(void (*fn)(share_mode_entry *, char *))
  252. {
  253.     return share_ops->forall(fn);
  254. }
  255.  
  256. /*******************************************************************
  257.  Dump the state of the system.
  258. ********************************************************************/
  259.  
  260. void share_status(FILE *f)
  261. {
  262.     share_ops->status(f);
  263. }
  264.